/*******************************************************************************
 * Copyright (c) 2011 TXT e-solutions SpA
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * This work was performed within the IoT_at_Work Project
 * and partially funded by the European Commission's
 * 7th Framework Programme under the research area ICT-2009.1.3
 * Internet of Things and enterprise environments.
 *
 *
 * Authors:
 *     Cristoforo Seccia (TXT e-solutions SpA)
 *
 * Contributors:
 *      Domenico Rotondi (TXT e-solutions SpA)
 *******************************************************************************/
package it.txt.access.capability.commons.signer.utils;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.security.auth.x500.X500Principal;

/**
 *
 * @author Cristoforo Seccia (TXT e-solutions SpA)
 * @author Salvatore Piccione (TXT e-solutions SpA - salvatore.piccione AT network.txtgroup.com)
 */
public class KeystoreHelper {

    private static final Logger logger = Logger.getLogger(KeystoreHelper.class.getName());

    public static KeyStore getKeyStore(String filename, char[] password) throws GeneralSecurityException {
        try {
            KeyStore result = KeyStore.getInstance(KeyStore.getDefaultType());
            FileInputStream in = new FileInputStream(filename);
            result.load(in, password);
            in.close();
            return result;
        } catch (IOException ex) {
            throw new GeneralSecurityException(ex.getMessage(), ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new GeneralSecurityException(ex.getMessage(), ex);
        } catch (CertificateException ex) {
            throw new GeneralSecurityException(ex.getMessage(), ex);
        }
    }

    public static KeyStore getKeyStore(InputStream in, char[] password) throws GeneralSecurityException {
        try {
            KeyStore result = KeyStore.getInstance(KeyStore.getDefaultType());
            result.load(in, password);
            return result;
        } catch (IOException ex) {
            throw new GeneralSecurityException(ex.getMessage(), ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new GeneralSecurityException(ex.getMessage(), ex);
        } catch (CertificateException ex) {
            throw new GeneralSecurityException(ex.getMessage(), ex);
        }
    }

    public static List<String> getAliases(KeyStore keystore)
            throws KeyStoreException {
        return Collections.list(keystore.aliases());
    }

    public static String getAlias(KeyStore keystore, java.security.cert.Certificate certificate)
            throws KeyStoreException {
        return keystore.getCertificateAlias(certificate);
    }

    public static Key getKey(KeyStore keystore, String alias, String password)
            throws GeneralSecurityException {
        return keystore.getKey(alias, password.toCharArray());
    }

    public static java.security.cert.Certificate getCertificateByAlias(KeyStore keystore, String alias)
            throws GeneralSecurityException {
        return keystore.getCertificate(alias);
    }

    public static java.security.cert.X509Certificate getX509CertificateByAlias(KeyStore keystore, String alias)
            throws GeneralSecurityException {
        return (X509Certificate) keystore.getCertificate(alias);
    }

    public static java.security.cert.X509Certificate getX509CertificateByIssuer(KeyStore keystore, String issuer)
            throws GeneralSecurityException {

        Enumeration<String> aliases = keystore.aliases();
        logger.log(Level.INFO, "Searching certificate issued to " + issuer + 
            ". Search parameter: the common name of the X.500 " +
            "distinguished name reported in the X.509 certificate");
        while (aliases.hasMoreElements()) {

            String alias = aliases.nextElement();

            logger.log(Level.FINE, "Current alias:: {0}.", alias);

            java.security.cert.Certificate cert = keystore.getCertificate(alias);
            X500Principal currentPrincipal;
            X509Certificate x509Certificate;
            if (cert instanceof java.security.cert.X509Certificate) {

                x509Certificate = (X509Certificate) cert;
                currentPrincipal = x509Certificate.getSubjectX500Principal();
                logger.log(Level.FINE, "Current subject X.500 principal:: {0}.", currentPrincipal);

                final String cn = new DNParser(currentPrincipal).find("cn");

                logger.log(Level.FINE, "Current common name:: {0}.", cn);

                if (cn.equals(issuer)) {
                    logger.log(Level.INFO, "Certificate found! Subject X.500 principal:: " + currentPrincipal);
                    return x509Certificate;
                }

                logger.log(Level.FINE, "Certificate not found. The search will continue.");
            }
        }
        return null;
    }
}
